Skip to content

feat(memory): procedural derived-stats compat helper + shadow-read drift#38

Merged
stackbilt-admin merged 1 commit intomainfrom
feat/port-compat-helper
Apr 24, 2026
Merged

feat(memory): procedural derived-stats compat helper + shadow-read drift#38
stackbilt-admin merged 1 commit intomainfrom
feat/port-compat-helper

Conversation

@stackbilt-admin
Copy link
Copy Markdown
Member

Summary

Moves the aegis#564 Phase 2 compat helper down from the daemon into core so public `/procedures` + `/dashboard` readers actually exercise it. Daemon's shadowed duplicates were dead code (Hono first-match-wins, core mounts first), so drift samples only came from the router hot path at 10% sampling — effectively blinding the Phase 3 readiness gauge. Closes #30.

Added

  • `episodic_memory.complexity_tier TEXT` column (aegis#563 prerequisite — the compat helper queries by it)
  • `shadow_read_drift` table + index (Phase 2 drift log)
  • `getEpisodeStatsByComplexity`, `getAllEpisodeStatsByComplexity`, `EpisodeStatsAggregate` in `kernel/memory/episodic.ts`
  • `DriftLogOpts`, `getProcedureWithDerivedStats`, `getAllProceduresWithDerivedStats` in `kernel/memory/procedural.ts` (plus internal `logDriftSingle` / `logDriftBulk` helpers)

Swapped

  • `dashboard.ts` → `getAllProceduresWithDerivedStats(db, { reader: 'dashboard' })`
  • `routes/observability.ts /procedures` → `getAllProceduresWithDerivedStats(c.env.DB, { reader: 'observability' })`

Scope note (partial aegis#563)

This picks up a slice of aegis#563 as prerequisite — only the `complexity_tier` column on `episodic_memory`, which the compat helper queries. Other aegis#563 columns (`executor_config`, `court_card`) are not touched here; they can land independently if needed.

Generic-library delta from daemon

Dropped daemon's `DERIVED_CUTOFF = '2026-04-22'` date guard. That cutoff is daemon-specific (when its migration ran); core is generic, any other consumer migrates on a different day. Rows with `complexity_tier IS NOT NULL` are treated as derivable; consumers wanting stricter protection against retroactive backfills can wrap with their own time filter.

Test plan

  • Core typecheck: clean
  • Core tests: 1474 passed, 1 skipped (observability.test.ts mock updated to match new export)
  • Daemon typecheck against this branch: clean
  • Consumers need to rerun `schema.sql` — adds one column + one table
  • Daemon follow-up PR: collapse `dashboard.ts` shadow + remove v2.1.6 `drift-probe` cron workaround

Refs aegis#564 Phase 2, aegis#563 (prereq), #35

…ift (closes #30)

Moves the aegis#564 Phase 2 compat helper down from the daemon into
core so the public /procedures + /dashboard readers actually exercise
it. Daemon's shadowed duplicates were dead code (core mounts first in
Hono), so drift samples only came from the router hot path at
10% sampling — effectively blinding the Phase 3 readiness gauge.

## Added

- `episodic_memory.complexity_tier TEXT` column (aegis#563 prerequisite
  — the compat helper queries by it)
- `shadow_read_drift` table + index — Phase 2 drift log
- `getEpisodeStatsByComplexity`, `getAllEpisodeStatsByComplexity`,
  `EpisodeStatsAggregate` in `kernel/memory/episodic.ts`
- `DriftLogOpts`, `getProcedureWithDerivedStats`,
  `getAllProceduresWithDerivedStats` in `kernel/memory/procedural.ts`
  (plus internal `logDriftSingle` / `logDriftBulk` / helpers)

## Swapped

- `dashboard.ts` → `getAllProceduresWithDerivedStats(db, { reader: 'dashboard' })`
- `routes/observability.ts /procedures` → `getAllProceduresWithDerivedStats(c.env.DB, { reader: 'observability' })`

## Scope note

This picks up a slice of aegis#563 as prerequisite — only the
`complexity_tier` column on `episodic_memory`, which the compat helper
queries. Other aegis#563 columns (`executor_config`, `court_card`) are
not touched here; they can land independently if needed. Not in scope.

## Generic-library delta from daemon

Dropped daemon's `DERIVED_CUTOFF = '2026-04-22'` date guard. That cutoff
is daemon-specific (when its migration ran); core is generic and any
other consumer migrates on a different day. Rows with `complexity_tier
IS NOT NULL` are treated as derivable; consumers wanting stricter
protection against retroactive backfills can wrap with their own time
filter.

## Test plan

- [x] Core typecheck: clean
- [x] Core tests: 1474 passed, 1 skipped (observability.test.ts mock
      updated to match new export)
- [x] Daemon typecheck against this branch: clean
- [ ] Consumers need to rerun `schema.sql` — adds one column + one table
- [ ] Daemon follow-up PR: collapse `dashboard.ts` shadow + remove
      v2.1.6 `drift-probe` cron workaround

Refs: aegis#564 Phase 2, aegis#563 (prereq), aegis-oss#35

Resolves-Request: aegis-oss#30
@stackbilt-admin stackbilt-admin force-pushed the feat/port-compat-helper branch from f55078f to 9864728 Compare April 24, 2026 00:05
@stackbilt-admin stackbilt-admin merged commit 3d74ca5 into main Apr 24, 2026
2 checks passed
@stackbilt-admin stackbilt-admin deleted the feat/port-compat-helper branch April 24, 2026 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

core: route procedural reads through a derived-stats compat helper (supports daemon aegis#564 Phase 2)

1 participant